/*
 * Created: Author: Aléx Carvalho / Date: Jan 24, 2015
 * 
 * Changed: $Author: ac280593@gmail.com $ / $Date: 2015-06-11 01:28:43 -0300 (Thu, 11 Jun 2015) $
 */
package com.cpm;

import com.cpm.context.SessionContext;
import com.cpm.entities.Information;
import com.cpm.repository.Filter;
import com.cpm.repository.ActionRepository;
import com.cpm.repository.CompetenceRepository;
import com.cpm.repository.FolderRepository;
import com.cpm.repository.IndicatorRepository;
import com.cpm.repository.InformationRepository;
import com.cpm.repository.NodeRepository;
import com.cpm.repository.StrategicPlanRepository;
import com.cpm.repository.UserRepository;
import com.cpm.wrapper.exception.SystemException;
import java.util.HashSet;
import java.util.Set;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.CDI;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class ServiceLocator {

    private ServiceLocator() {
    }

    public static ActionRepository getActionRepository() {
        return lookup(ActionRepository.class);
    }

    public static CompetenceRepository getCompetenceRepository() {
        return lookup(CompetenceRepository.class);
    }

    public static FolderRepository getFolderRepository() {
        return lookup(FolderRepository.class);
    }

    public static IndicatorRepository getIndicatorRepository() {
        return lookup(IndicatorRepository.class);
    }

    public static StrategicPlanRepository getStrategicPlanRepository() {
        return lookup(StrategicPlanRepository.class);
    }

    public static UserRepository getUserRepository() {
        return lookup(UserRepository.class);
    }
    
    public static NodeRepository getNodeRepository() {
        return lookup(NodeRepository.class);
    }
    
    public static InformationRepository getInformationRepository() {
        return lookup(InformationRepository.class);
    }
    
    public static Filter getFilter() {
        return lookup(Filter.class);
    }

    public static SessionContext getSessionContext() {
        return lookup(SessionContext.class);
    }

    public static <T> T lookup(final Class<T> clazz) {
        BeanManager manager = getBeanManager();

        Bean<T> bean = (Bean<T>) manager.resolve( getBeans(manager, clazz) );

        CreationalContext<T> context = manager.createCreationalContext(bean);

        return (T) manager.getReference(bean, clazz, context);
    }
    
    public static <T> Set<T> lookupAll(final Class<T> clazz) {
        final Set<T> values = new HashSet<>(0);
        
        final BeanManager manager = getBeanManager();
        
        getBeans(manager, clazz).forEach( (Bean bean) -> {
            
            CreationalContext<T> context = manager.createCreationalContext(bean);
            values.add((T) manager.getReference(bean, clazz, context));
        } );
        
        return values;
        
    }

    private static Set<Bean<?>> getBeans(BeanManager manager, final Class clazz) {
        Set<Bean<?>> beans = manager.getBeans(clazz);

        if (beans == null || beans.isEmpty()) {
            throw new SystemException("CDI BeanManager cannot find an instance of requested type " + clazz.getName());
        }

        return beans;
    }
    
    private static BeanManager getBeanManager(){
//        try {
//            InitialContext ctx = new InitialContext();
//
//            return (BeanManager) ctx.lookup("java:comp/BeanManager");
            return CDI.current().getBeanManager();
//        }
//        catch (NamingException e) {
//            throw new SystemException("Not found BeanManager");
//        }
    }
}
